#include <fstream>
#include <stdexcept>
#include <algorithm>
#include <stdlib.h>
#include "Config.h"
#include "Definitions.h"
#ifdef GCFG_DEBUG
	#include <iostream>
#endif

Config* Config::pInstance = 0;			// initialize static pointer
/*********************************************/
Config* Config::Instance( ) 
{
	if (pInstance == 0) { 			// is it the first call?  
		pInstance = new Config; 	// if so create a new instance
		pInstance->fileParse = false;
	}
	return pInstance; 			// return the address of the sole instance
}
/*********************************************/
void Config::Destruct( )
{
	if (pInstance != 0 ) delete( pInstance );
}
/*********************************************/
Config::~Config()
{
}
/*********************************************/
bool Config::isCompleteConfig()
{
	if ( !pInstance->fileParse )
		throw( std::logic_error("No file parsed yet!"));

	std::sort( minCfg.begin(), minCfg.end() );
	std::vector<std::string>::iterator new_end_pos;
	new_end_pos = std::unique( minCfg.begin(), minCfg.end() );
	minCfg.erase( new_end_pos, minCfg.end() );
}
/*********************************************/
void Config::addMinimumConfig( const std::string& cmd )
{
	minCfg.push_back( cmd );
}
/*********************************************/
void Config::parseFile( const std::string& file_loc ) 
{
	std::ifstream	file;

	// Acquire resources
	try  {
		std::string line;

		file.open( file_loc.c_str(), std::ios::in );
		if ( !file.is_open() )
			throw( std::logic_error("Could not open configuration file: " + file_loc + "!"));
#ifdef GCFG_DEBUG
		uint32		lineError = 0;
#endif
		while ( getline ( file, line ) ) {
#ifdef GCFG_DEBUG
			lineError++;
#endif
			std::string::size_type i = line.find_first_not_of ( " \t\n\v" );
			if ((i != std::string::npos && line[i] == '#') || line.empty()) {
#ifdef GCFG_DEBUG
				std::cout << "Ignore: " << line << std::endl;
#endif
				continue;
			}
			
			size_t found = line.find_first_of(" ");
			if ( found == std::string::npos ) {
#ifdef GCFG_DEBUG	
				std::cout << "Error on line " << lineError << ":\n " << line << std::endl; 
#endif
				throw( std::logic_error("Syntax error in configuration file!"));
			}
			
			std::string	cmd = line.substr(0, found);
			std::string 	val = line.substr(found);
#ifdef GCFG_DEBUG
			std::cout << "Set value: " << cmd << " to " << atoi(val.c_str()) << std::endl;
#endif
			
			values[cmd.c_str()] = atoi(val.c_str());
		}
#ifdef GCFG_DEBUG
	std::cout << "Parse Succesfull" << std::endl;
#endif
	}
	catch (...) {
		if ( file.is_open() ) file.close();
		throw;
	}
	fileParse = true;
	return;
}
/*********************************************/
bool Config::test( const std::string& cmd )
{
	std::map<std::string,sint32>::iterator it = values.find(cmd);
	if ( it == values.end() )
		return( false );
	else 
		return( true );
}
/*********************************************/
void Config::set( const std::string& cmd, sint32 value)
{
	values[cmd.c_str()] = value;
}
/*********************************************/
sint32 Config::get( const std::string& cmd )
{
	if (( fileParse ) && ( test(cmd) )) return( values[cmd.c_str()] );
	else throw (std::logic_error("Config value requested while no file has been parsed or the requested value wasn't specified!"));
}
/*********************************************/